package cs304.p3.library.service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.sql.SQLException;
import java.text.SimpleDateFormat;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import cs304.p3.library.domain.Book;
import cs304.p3.library.domain.BookCopy.BookStatus;
import cs304.p3.library.domain.Borrower;
import cs304.p3.library.exceptions.InvalidBorrowerException;
import cs304.p3.library.util.SqlUtils;

public class BorrowerService extends Service {

	/**
	 * Search titles, authors, and subjects for books using any of these keywords.
	 * 
	 * @param keywords Titles, authors OR subjects.
	 * @return
	 */
	public List<Book> search(List<String> titles, List<String> authors, List<String> subjects) {
		List<Book> books = Lists.newArrayList();
		try {
			List<String> callNumbers = bookDao.selectBook(titles, authors, subjects);
			for(String callNumber : callNumbers) {
				Book book = bookDao.selectBook(callNumber);
				int[] counts = bookDao.countInOut(callNumber);
				book.setInCount(counts[0]);
				book.setOutCount(counts[1]);
				books.add(book);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return books;
	}

	/**
	 * Get borrower's account info, borrowed items, outstanding fines, hold requests.
	 */
	public Borrower getAccount(String bid, String password) throws InvalidBorrowerException {
		Map<String, String> values = Maps.newHashMap();
		values.put("bid", bid);
		try {
			Borrower b = borrowerDao.selectBorrower(bid, password);
			if(b != null) {
				return b;
			}
			// TODO message should be "invalid ID/password combination"
			throw new InvalidBorrowerException("BID or Password");

		} catch(SQLException e) {
			try {
				System.err.println(e.getMessage());
				System.err.println("Failed to retrieve account info; rolling back.");
				connection.rollback();
			} catch(SQLException e1) {
				throw new RuntimeException();
			}
		}
		return null;
	}

	public void placeHoldRequest(String bid, String callNumber) {
		UUID id = UUID.randomUUID();
		String hid = Long.toHexString(id.getMostSignificantBits())
				+ Long.toHexString(id.getLeastSignificantBits());
		String issuedDate = SqlUtils.getDateString(new Date());
		try {
			//TODO check if theres an available bookcopy,
			// if yes, then put it on hold and delete the hold request
			bookDao.selectBookCopy(callNumber, SqlUtils.ANY_VALUE, BookStatus.OUT.toString());
			
			holdRequestDao.insertHoldRequest(hid, bid, callNumber, issuedDate);
		} catch (SQLException e) {
			// TODO Need exception to show that hold request failed
			e.printStackTrace();
		}
	}
	
	public void placeHoldRequest(String bid, List<String> callNumbers) {
		int count = 0;
		for(String callNum : callNumbers){
			UUID id = UUID.randomUUID();
			String hid = Long.toHexString(id.getMostSignificantBits())
					+ Long.toHexString(id.getLeastSignificantBits());
			String issuedDate = SqlUtils.getDateString(new Date());
			try {
				//TODO check if theres an available bookcopy,
				// if yes, then put it on hold and delete the hold request or 
				// mark it as fulfilled somehow
				holdRequestDao.insertHoldRequest(hid, bid, callNum, issuedDate);
				count++;
			} catch (SQLException e) {
				// TODO Need exception to show that hold request failed
				e.printStackTrace();
			}
		}
		System.out.println("Inserted " + count + " hold requests");
	}

	public void payFine(String fid) {
		Date todayDate = new Date();
		SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");

		String paidDate = dateformat.format(todayDate);

		try {
			fineDao.updateFine(fid, paidDate);
		} catch(SQLException e) {
			try {
				System.err.println("Paying fines failed; rolling back.");
				connection.rollback();
			} catch(SQLException e1) {
				throw new RuntimeException();
			}

		}
	}
}
